package terra.model.object.map;

import terra.Config;
import terra.definitions.GroundDef;
import terra.managers.DefManager;
import terra.managers.MapManager;
import terra.model.World;
import terra.model.map.Map;
import terra.model.object.GObject;
import terra.network.Connections;
import terra.network.packet.server.TileInfo;

/** Класс представляет воздух и воду (жидкость) */
public class MapObject extends AbstractMapObject {
	private static final long serialVersionUID = 882705594733831419L;

	private float mass;
	private transient float oldMass;
	private float newMass;
	public boolean isWater = false;

	public MapObject(int x, int y, short tX, short tY, GroundDef def, Map map) {
		super(x, y, tX, tY, map);
		setId((short) def.id);
		setMass(def.mass);
	}

	public MapObject(MapObject obj) {
		super(obj);
		setId(obj.getId());
		setMass(obj.getMass());
		setNewMass(obj.getNewMass());
		obj.listenChanges();
		tileChanged();
	}

	public MapObject(GroundObject obj) {
		super(obj);
		setId(obj.getId());
		setMass(obj.getDef().getFloatProperty("mass"));
		setNewMass(getMass());
		obj.listenChanges();
		// tileChanged();
	}

	public MapObject(AbstractMapObject obj, short id) {
		super(obj);
		setId(id);
		obj.listenChanges();
		tileChanged();
	}

	public MapObject(int x, int y, int tX, int tY, int mapIndex) {
		super(x, y, (short) tX, (short) tY, MapManager.getInstance().getMaps()
				.get(mapIndex));
		setId((short) -1);
	}

	public boolean canMove() {
		return true;
	}

	public String getImage() {
		return getDef().image;
	}

	public String getBackgroundImage() {
		if (getBackgroundId() != -1)
			return getDef(getBackgroundId()).image + "_back";
		return "block_sky";
	}

	public void setMass(float mass) {
		// setOldMass(this.mass);
		if (!isWater) {
			if (mass != 0) {
				getMap().getWater().add(this);
				isWater = true;
			}
		}
		this.mass = mass;
	}

	public float getMass() {
		return mass;
	}

	public void addNewMass(float m) {
		if (!isWater) {
			getMap().getWater().add(this);
			isWater = true;
		}
		newMass += m;
	}

	public void removeNewMass(float m) {
		newMass -= m;
	}

	public void setNewMass(float m) {
		newMass = m;
	}

	public float getNewMass() {
		return newMass;
	}

	public void setMassFromNew() {
		setMass(getNewMass());
	}

	public void nullMass() {
		mass = 0;
		oldMass = 0;
		newMass = 0;
		getMap().getWater().remove(this);
		isWater = false;
		// System.out.println("nullMass " + getX() + "_" + getY());
		World.getInstance().addNulledWater(this);
	}

	public byte getType() {
		if (getMass() >= Config.MinMass)
			return TYPE_WATER;
		else
			return TYPE_AIR;
	}

	public short getId() {
		return id;
	}

	public short getBackgroundId() {
		return id;
	}

	/**
	 * Если тайл из пустого стал непустым - да Если тайл из полного стал пустым
	 * - да Если масса изменилась больше чем на 0,2 - да Старая масса должна
	 * изменяться при отправке тайла
	 */

	public boolean massChanged() {
		// if ((getOldMass() == 0 && getMass() != 0)
		// || (getOldMass() != 0 && getMass() == 0)) {
		// return true;
		// }
		if (getMass() >= 1f)
			return false;
		float diff = Math.abs(getMass() - getOldMass());
		if (diff >= 0.02f) {
			return true;
		}
		return false;
	}

	public GroundDef getDef() {
		return DefManager.groundDefs.get((int) getId());
	}

	@Override
	public String getName() {
		return getDef().getStringProperty("name");
	}

	@Override
	public void objectChanged(GObject object) {

	}

	@Override
	protected void applyChange(AbstractMapObject mapObject) {

	}

	public MapObject createNeighbor(int position) {
		int tX = getTileX(), tY = getTileY();
		int x1 = getX(), y1 = getY();
		int mapIndex = getMap().index;
		if (position == DOWN) {
			if (tY == Config.mapHeight - 1)
				return null;
			tY++;
			y1 += Config.tileSize;
		} else if (position == LEFT) {
			if (tX == 0) {
				tX = Config.mapWidth;
				mapIndex--;
			}
			tX--;
			x1 -= Config.tileSize;
		} else if (position == RIGHT) {
			if (tX == Config.mapWidth - 1) {
				tX = -1;
				mapIndex++;
			}
			tX++;
			x1 += Config.tileSize;
		} else if (position == UP) {
			if (tY <= 0)
				return null;
			tY--;
			y1 -= Config.tileSize;
		}
		if (!MapManager.getInstance().getMaps().containsKey(mapIndex))
			return null;
		MapObject object = new MapObject(x1, y1, tX, tY, mapIndex);
		object.getMap().getMap()[tX][tY] = object;
		return object;
	}

	@Override
	public void sendTileInfo() {
		setOldMass(getMass());
		// FIXME getMap().send(getTileInfo(), true);
		Connections.broadcast(getTileInfo());
	}

	@Override
	public TileInfo getTileInfo() {
		TileInfo info = new TileInfo(getX() / Config.tileSize, getY()
				/ Config.tileSize, getType());
		info.mass = getMass();
		info.id = getId();
		return info;
	}

	public float getOldMass() {
		return oldMass;
	}

	public void setOldMass(float oldMass) {
		this.oldMass = oldMass;
	}
}
